package com.dance.netty.netty.groupchar;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class NettyServerHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 定义一个Channel组, 用于管理所有的channel
     *  GlobalEventExecutor.INSTANCE : 是一个全局的事件执行器, 是一个单例
     */
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 表示建立连接, 一旦连接, 第一个执行
     * @param ctx 上下文对象
     * @throws Exception 异常
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        /*
         * 将该用户加入聊天的信息提送给其他客户端
         * 该方法会将 channelGroup 中 所有的Channel遍历 并发送
         */
        channelGroup.writeAndFlush("[客户端]:" + channel.remoteAddress() +" " + dateTimeFormatter.format(LocalDateTime.now()) + " 加入聊天\n" );
        // 加入到组中 因为先发送后加入, 就不会发送给自己了
        channelGroup.add(channel);
    }

    /**
     * 表示Channel处于活跃的状态
     * @param ctx 上下文对象
     * @throws Exception 异常
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("[客户端]: " +ctx.channel().remoteAddress() + " 上线了~" +" " + dateTimeFormatter.format(LocalDateTime.now()));
    }

    /**
     * 表示Channel处于非活跃状态
     * @param ctx 上下文对象
     * @throws Exception 异常
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("[客户端]: " + ctx.channel().remoteAddress() + " 离线了~" +" " + dateTimeFormatter.format(LocalDateTime.now()));
    }

    /**
     * 表示断开连接
     * @param ctx 上下文对象
     * @throws Exception 异常
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        // 会自动将channel从ChannelGroup中移除, 不需要手动
        channelGroup.writeAndFlush(ctx.channel().remoteAddress() + " 离开了~" +" " + dateTimeFormatter.format(LocalDateTime.now()));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.forEach(x -> {
            // 排除自己
            if(channel != x){
                x.writeAndFlush("[客户] : " + channel.remoteAddress() +" " + dateTimeFormatter.format(LocalDateTime.now()) + " 发送了 -> " +msg + "\n");
            }else{
                // 回显自己
                x.writeAndFlush("[自己] : " + channel.remoteAddress()+" " + dateTimeFormatter.format(LocalDateTime.now()) + " 发送了 -> " +msg + "\n");
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.channel().close();
    }
}
